package org.agile4j.plugin.soap;

import java.util.Set;

import javax.servlet.ServletConfig;
import javax.servlet.annotation.WebServlet;

import org.agle4j.framework.helper.BeanHelper;
import org.agle4j.framework.helper.ClassHelper;
import org.agle4j.framework.utils.CollectionUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.transport.servlet.CXFNonSpringServlet;

/**
 * SOAP servlet
 * Servlet 初始化时 初始化CXF总线与 发布SOAP服务
 * 
 * @author hanyx
 * @since 1.0.0
 */
@WebServlet(urlPatterns=SoapConstant.SERVLET_URL, loadOnStartup=0)
public class SoapServlet extends CXFNonSpringServlet {

	@Override
	protected void loadBus(ServletConfig sc) {
		// 初始化 CXF 服务总线
		super.loadBus(sc);
		Bus bus = getBus();
		BusFactory.setDefaultBus(bus);
		// 发布 SOAP 服务
		publishSoapSerivce();
	}
	
	private void publishSoapSerivce() {
		// 遍历所有标注了 SOAP 注解的类 
		Set<Class<?>> soapClassSet = ClassHelper.getClassSetByAnnotation(Soap.class) ;
		if (CollectionUtil.isEmpty(soapClassSet)) {
			for (Class<?> soapClass : soapClassSet) {
				// 获取 SOAP 地址
				String address = getAddress(soapClass) ;
				// 获取 SOAP 类的接口
				Class<?> soapLInterfaceClass = getSopaInterfaceClass(soapClass) ;
				// 获取 SOAP 类的实例
				Object soapIntance = BeanHelper.getBean(soapClass) ;
				// 发布 SOAP 服务
				SoapHelper.publishService(address, soapLInterfaceClass, soapIntance);
			}
		}
	}

	private String getAddress(Class<?> soapClass) {
		String address ;
		// 若 SOAP 注解的value 属性不为空, 则获取当前值, 否则获取类名.
		String soapValue = soapClass.getAnnotation(Soap.class).value() ;
		if (StringUtils.isNotEmpty(soapValue)) {
			address = soapValue ;
		} else {
			address = getSopaInterfaceClass(soapClass).getSimpleName() ;
		}
		// 确保最前面只有一个 /
		if (!address.startsWith("/")) {
			address = "/" + address ;
		}
		address = StringUtils.replacePattern(address, "\\/+", "/") ;
		return null;
	}

	private Class<?> getSopaInterfaceClass(Class<?> soapClass) {
		// 获取 SOAP 实现类的第一个接口作为SOAP 服务接口
		return soapClass.getInterfaces()[0];
	}
	
}
